<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes">
<title>WebGL Caves Demo</title>
<style>
html, body {
  width: 100%;
  height: 100%;
  border: 0px;
  padding: 0px;
  margin: 0px;
  background-color: grey;
  text-align: center;
}
canvas#render_area {
  border-radius: 10px;
  border: black solid 10px;
  background-color: brown;
}
#centerer {
  width: 100%;
  height: 100%;
  display: table;
}
#viewContainer {
  vertical-align: middle;
  display: table-cell;
}
#info {
  position: absolute;
  left: 10px;
  bottom: 10px;
  z-index: 3;
  width: 300px;
  padding: 10px;
  border-radius: 10px;
  background-color: rgba(255, 255, 255, 0.5);
}
</style>
<script src="../jquery-ui-1.8.2.custom/js/jquery-1.4.2.min.js"></script>
<script src="../tdl/base.js"></script>
<script src="growable.js"></script>
<script src="field.js"></script>
<script src="display_list.js"></script>
<script src="marching_cubes_tables.js"></script>
<script src="marching_cubes.js"></script>
<script src="caves_main.js"></script>
<script>

tdl.require('tdl.fast');
tdl.require('tdl.math');
tdl.require('tdl.primitives');
tdl.require('tdl.shader');
tdl.require('tdl.programs');
tdl.require('tdl.log');
tdl.require('tdl.models');
tdl.require('tdl.buffers');
tdl.require('tdl.framebuffers');
tdl.require('tdl.textures');
tdl.require('tdl.webgl');

var gl;
var canvas;
var aspect;

// Use this to refer to the backbuffer as if it were another framebuffer
var backbuffer;

function initializeGraphics() {
  canvas = document.getElementById('render_area');
  gl = tdl.webgl.setupWebGL(canvas);
  if (!gl) {
  return false;
  }
//  gl = tdl.webgl.makeDebugContext(wu.create3DContext(canvas));
  aspect = canvas.clientWidth / canvas.clientHeight;
  backbuffer = tdl.framebuffers.getBackBuffer(canvas);

  // Set some sane defaults.
  gl.disable(gl.BLEND);
  gl.depthFunc(gl.LEQUAL);
  gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);

  return true;
}

var caves = null;
var timeLastLoop, timeLastEvent;

function mainLoop() {
  var timeNow = (new Date()).getTime() * 0.001;
  var timeDelta = timeNow - timeLastLoop;
  timeLastLoop = timeNow;

  aspect = canvas.clientWidth / canvas.clientHeight;

  caves.tick(timeDelta);
  caves.render(backbuffer);

  if (timeNow - timeLastEvent < 300) {
    setTimeout(mainLoop, 0);
  } else {
    // No user interaction for a while, slow down tick rate.
    setTimeout(mainLoop, 1000);
  }
}

$(document).ready(function() {
  if (!initializeGraphics()) {
    return;
  }

  caves = new CavesMain();
  timeLastLoop = timeLastEvent = (new Date()).getTime() * 0.001;

  mainLoop();
})

$(document).mousemove(function(event) {
  if (caves !== null) {
    var offset = $('canvas#render_area').offset();
    var x = event.pageX - offset.left;
    var y = event.pageY - offset.top;
    caves.onMouseMove(x, y);
    timeLastEvent = timeLastLoop;
  }
})

$(document).mousedown(function(event) {
  if (caves !== null) {
    caves.onMouseDown(event.which);
    timeLastEvent = timeLastLoop;
  }
})

$(document).mouseup(function(event) {
  if (caves !== null) {
    caves.onMouseUp(event.which);
    timeLastEvent = timeLastLoop;
  }
})

$(document).keydown(function(event) {
  if (caves !== null) {
    caves.onKeyDown(event.which);
    timeLastEvent = timeLastLoop;
  }
})

$(document).keyup(function(event) {
  if (caves !== null) {
    caves.onKeyUp(event.which);
    timeLastEvent = timeLastLoop;
  }
})

</script>

</head>

<body>
<div id="centerer">
<div id="viewContainer">
  <canvas id="render_area" width="1024" height="512"></canvas>
</div>
</div>
<div id="info">
Move with W,S,A,D. Shift to increase speed.<br />
Hold left mouse button to carve.
</div>
</body>

<script id="marching_cube_fs" type="x-shader/x-fragment">
  #ifdef GL_FRAGMENT_PRECISION_HIGH
    precision highp float;
  #else
    precision mediump float;
  #endif

  uniform vec4 u_ambientUp;
  uniform vec4 u_ambientDown;
  uniform vec3 u_lightDir;
  uniform vec4 u_lightColor;
  uniform sampler2D diffuseSamplerWall;
  uniform sampler2D diffuseSamplerFloor;

  varying vec3 v_worldPos;
  //varying vec4 v_color;
  varying vec3 v_normal;
  varying vec3 v_eyeDir;

  void main(void) {
    vec4 diffuseX = texture2D(diffuseSamplerWall, vec2(v_worldPos.y, v_worldPos.z) * 0.1);
    vec4 diffuseY = texture2D(diffuseSamplerWall, vec2(v_worldPos.z, v_worldPos.x) * 0.1);
    vec4 diffuseZ = texture2D(diffuseSamplerFloor, vec2(v_worldPos.x, v_worldPos.y) * 0.1);
    vec3 normal = normalize(v_normal);
    vec3 diff_blend = normal * normal;
    vec4 diffuse = diffuseX * diff_blend.x + diffuseY * diff_blend.y + diffuseZ * diff_blend.z;
    float light = max(0.0, dot(normalize(u_lightDir), normal));
    float glare = max(0.0, dot(v_normal, normalize(v_eyeDir + u_lightDir)));
    glare = glare*glare;
    glare = glare*glare;
    glare = glare*glare;
    glare = glare*glare;
    glare = glare*glare;
    glare = glare*glare;
    vec4 ambient = mix(u_ambientDown, u_ambientUp, (normal.z + 1.0)/2.0);
    // Gamma correction approximation (sqrt)
    gl_FragColor = vec4((sqrt(ambient + light * u_lightColor) * diffuse).xyz, 1.0);
  }
</script>

<script id="marching_cube_vs" type="x-shader/x-vertex">
  attribute vec3 position;
  attribute vec3 normal;
  attribute vec2 texCoord;

  uniform mat4 u_worldviewproj;
  uniform mat4 u_worldview;
  uniform mat4 u_world;

  varying vec3 v_worldPos;
  //varying vec4 v_color;
  varying vec3 v_normal;
  varying vec3 v_eyeDir;

  void main(void) {
    //v_color = vec4(position.x + 0.5, position.y + 0.5, position.z + 0.5, 1.0);
    v_normal = (u_world * vec4(normal, 0.0)).xyz;
    //v_normal = vec3(0.0, 0.0, 1.0);
    v_eyeDir = -normalize((u_worldview * vec4(position, 1.0)).xyz);
    v_worldPos = position;
    gl_Position = u_worldviewproj * vec4(position, 1.0);
  }
</script>

</html>
